/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.view.controller;


import cz.cvut.fel.taskpro.business.imanager.IAssignmentBusiness;
import cz.cvut.fel.taskpro.business.imanager.IGroupBusiness;
import cz.cvut.fel.taskpro.business.imanager.ISubjectBusiness;
import cz.cvut.fel.taskpro.business.imanager.ITeamBusiness;
import cz.cvut.fel.taskpro.business.imanager.IUserBusiness;
import cz.cvut.fel.taskpro.business.imanager.IVersionBusiness;
import cz.cvut.fel.taskpro.business.support.BusinessRuleException;
import cz.cvut.fel.taskpro.business.support.TaskProException;
import cz.cvut.fel.taskpro.data.entity.Assignment;
import cz.cvut.fel.taskpro.data.entity.AssignmentSubmit;
import cz.cvut.fel.taskpro.data.entity.AssignmentSubmit.State;
import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Subject;
import cz.cvut.fel.taskpro.data.entity.Team;
import cz.cvut.fel.taskpro.data.entity.Template;
import cz.cvut.fel.taskpro.data.entity.VersionFile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

/**
 * This controlelr is responsible for creating task, assignment and rate
 * assignment. This controller is session scoped and is called as
 * kantorTaskBean.
 *
 * @author Tom
 * @version 1.0.0. beta
 */
@ManagedBean(name = "kantorTaskBean")
@SessionScoped
public class KantroTaskController extends AbstractFileController implements Serializable {

    private boolean showGroupsTable;
    private boolean showTeamsTable;
    private boolean showStudentsTable;
    private boolean isSubjecTask;
    private boolean notifyUsers;
    @EJB
    private IUserBusiness userB;
    @EJB
    private ISubjectBusiness subjectB;
    @EJB
    private ITeamBusiness teamB;
    @EJB
    private IGroupBusiness groupB;
    @EJB
    private IVersionBusiness versionB;
    @EJB
    private IAssignmentBusiness assignmentB;
    private Student[] selectedStudents;
    private GroupTaskPro[] selectedGroup;
    private Subject selectedSubject;
    private Subject[] selectedSubjects;
    private Team[] selectedTeam;
    private List<Template> kantorTemplate;
    private Template[] selectedTemplate;
    private List<Subject> kantorSubjects;
    private List<GroupTaskPro> kantorGroups;
    private List<Team> kantorTeam;
    private List<Assignment> finalAssignments;
    private boolean isDeadlineExpired;
    private boolean isGroupTask;
    private boolean isTeamTask;
    private boolean isStudentTask;
    private boolean displaySubTaskForm;
    private List<Student> kantorStudents;
    private List<AssignmentSubmit> submitTasks;
    private AssignmentSubmit submitTaskChoosen;
    private List<VersionFile> versions;
    private List<AssignmentSubmit.State> statesOfTask;
    private AssignmentSubmit.State[] selectedStates;
    private Team teamOnAssignmentSubmit;
    private Template selectedSingleTemplate;

    /**
     * This method ask business layer for all subject which teach logged kantor
     * and then ask business layer for all templates which were created by
     * logged kantor.
     *
     * @return string sequence assignTaskKantor
     * @see
     * ISubjectBusiness#getSubjectsByTeacher(cz.cvut.fel.taskpro.data.entity.Kantor)
     * @see
     * IAssignmentBusiness#getTemplateByKantor(cz.cvut.fel.taskpro.data.entity.Kantor)
     */
    public String chooseTargetUsers() {
        try {
            kantorSubjects = subjectB.getSubjectsByTeacher(loggedKantor);
            kantorTemplate = assignmentB.getTemplateByKantor(loggedKantor);
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
        return "assignTaskKantor";
    }

    /**
     * This class prepare class to assign template. The {@linkplain KantroTaskController#resetClass()
     * }
     * method is called and then business layer is asked for all template which
     * kantor created.
     *
     * @return string sequence assignTemplate
     * @see
     * IAssignmentBusiness#getTemplateByKantor(cz.cvut.fel.taskpro.data.entity.Kantor)
     */
    public String templateAssign() {
        resetClass();
        kantorTemplate = assignmentB.getTemplateByKantor(loggedKantor);
        return "assignTemplate";
    }

    /**
     * This method reset class. All variables are set up to null.
     */
    protected void resetClass() {
        kantorSubjects = null;
        kantorStudents = null;
        kantorGroups = null;
        kantorTeam = null;
        kantorTemplate = null;
        selectedGroup = null;
        selectedStudents = null;
        selectedSubject = null;
        selectedTemplate = null;
        selectedTeam = null;
        selectedSubjects = null;
        isGroupTask = false;
        isStudentTask = false;
        isTeamTask = false;
        showGroupsTable = false;
        showStudentsTable = false;
        showTeamsTable = false;
        isSubjecTask = false;
        submitTasks = null;
        displaySubTaskForm = false;
        submitTaskChoosen = null;
        isDeadlineExpired = false;
        teamOnAssignmentSubmit = null;
        selectedSingleTemplate = null;
    }

    /**
     * This method ask business layer for rate selected submitted task.
     *
     * @see
     * IAssignmentBusiness#rateTask(cz.cvut.fel.taskpro.data.entity.AssignmentSubmit)
     */
    public void rateTask() {
        try {
            assignmentB.rateTask(submitTaskChoosen);
            printSuccMessage("Task rate: ", "task was successfully rated");
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        } catch (TaskProException e) {
            printErrMessage(e.getExceptionCode(), e.getErrorMessage());
        }
    }

    /**
     * This method prepare class to rate task. First class is reset by
     * {@linkplain KantroTaskController#resetClass() } and then is business
     * layer asked fo all subject which teach logged user.
     *
     * @return string literal rateTask
     * @see
     * ISubjectBusiness#getSubjectsByTeacher(cz.cvut.fel.taskpro.data.entity.Kantor)
     */
    public String loadToRateTask() {
        resetClass();
        try {
            kantorSubjects = subjectB.getSubjectsByTeacher(loggedKantor);
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
        return "rateTask";
    }

    /**
     * This method initialize class after construcition. The method
     * {@linkplain KantroTaskController#recognizeLogin() } is called.
     */
    @PostConstruct
    public void init() {
        recognizeLogin();

    }

    /**
     * This method filter kantor groups, teams and students, by selected
     * subject. Groups, teams and students which will be returned must be part
     * of selected subejct. The rendered view parameter are reseted.
     *
     * @see IGroupBusiness#getGroups(cz.cvut.fel.taskpro.data.entity.Subject,
     * cz.cvut.fel.taskpro.data.entity.Kantor)
     * @see ITeamBusiness#getTeamsByGroup(java.util.List)
     * @see IUserBusiness#getStudentsByGroup(java.util.List)
     */
    public void filterBySubject() {
        showGroupsTable = true;
        showTeamsTable = true;
        showStudentsTable = true;
        isGroupTask = true;
        isStudentTask = false;
        isTeamTask = false;
        kantorGroups = groupB.getGroups(selectedSubject, loggedKantor);
        kantorTeam = teamB.getTeamsByGroup(kantorGroups);
        kantorStudents = userB.getStudentsByGroup(kantorGroups);
    }

    /**
     * This method filter kantor groups, teams and students, by selected
     * subjects. Groups, teams and students which will be returned must be part
     * of selected subejcts. The rendered view parameter are reseted.
     *
     * @see IGroupBusiness#getGroups(java.util.List,
     * cz.cvut.fel.taskpro.data.entity.Kantor)
     * @see ITeamBusiness#getTeamsByGroup(java.util.List)
     * @see IUserBusiness#getStudentsByGroup(java.util.List)
     */
    public void filterBySubjects() {
        showGroupsTable = true;
        showTeamsTable = true;
        showStudentsTable = true;
        isGroupTask = false;
        isTeamTask = false;
        isSubjecTask = true;
        kantorGroups = groupB.getGroups(Arrays.asList(selectedSubjects), loggedKantor);
        kantorTeam = teamB.getTeamsByGroup(kantorGroups);
        kantorStudents = userB.getStudentsByGroup(kantorGroups);
    }

    /**
     * This method filter kantor teams and students, by selected groups. Teams
     * and students which will be returned must be part of selected groups.
     *
     * @see ITeamBusiness#getTeamsByGroup(java.util.List)
     * @see IUserBusiness#getStudentsByGroup(java.util.List)
     */
    public void filterByGroup() {
        isGroupTask = true;
        isSubjecTask = false;
        isTeamTask = false;
        List<GroupTaskPro> sGroups = Arrays.asList(selectedGroup);
        kantorGroups = sGroups;
        kantorTeam = teamB.getTeamsByGroup(kantorGroups);
        kantorStudents = userB.getStudentsByGroup(kantorGroups);
    }

    /**
     * This method filter kantor students, by selected teams. Students which
     * will be returned must be part of selected teams.
     *
     * @see IUserBusiness#getStudentsByTeam(java.util.List)
     */
    public void filterByTeam() {
        isGroupTask = false;
        isStudentTask = false;
        isTeamTask = true;
        List<Team> sTeam = Arrays.asList(selectedTeam);
        kantorTeam = sTeam;
        kantorStudents = userB.getStudentsByTeam(sTeam);
    }

    /**
     * This method filter kantor students, by selected students. Students which
     * will be returned must be selected.
     */
    public void filterByStudent() {
        isGroupTask = false;
        isStudentTask = true;
        isTeamTask = false;
        kantorStudents = Arrays.asList(selectedStudents);
    }

    /**
     * This method create assignments which will be assigned. Based on type of
     * assignemnts are created assigments. There is created assignments for all
     * selected templates. This method dont add these assignments to datbase or
     * ask other layer for this action.
     *
     * @return string assigTaskKantor is return if there is no selected template
     * or there is no selected type of assignment otherwise is string
     * assigTaskConfirm is returned.
     *
     */
    public String makeSummarization() {
        List<Assignment> assignments = new ArrayList<Assignment>();
        if (selectedTemplate == null) {
            printErrMessage("Assigned task output", "No assignment was selected");
            return "assignTaskKantor";
        }
        List<Template> sTemplatte = Arrays.asList(selectedTemplate);
        if (sTemplatte.isEmpty()) {
            printErrMessage("Assigned task output", "No assignment was selected");
            return "assignTaskKantor";
        }
        Iterator templateIt = sTemplatte.iterator();
        while (templateIt.hasNext()) {
            Template currTemplate = (Template) templateIt.next();
            Assignment newAssignment;
            if (isGroupTask) {
                //  List<GroupTaskPro> sGroups=Arrays.asList(selectedGroup);
                newAssignment = new Assignment(null, null, null, currTemplate, kantorGroups, Assignment.Type.GROUP, selectedSubject);
            } else if (isTeamTask) {
                //List<Team> sTeam=Arrays.asList(selectedTeam);
                newAssignment = new Assignment(null, kantorTeam, null, currTemplate, null, Assignment.Type.TEAM, selectedSubject);
            } else if (isStudentTask) {
                List<Student> sStudent = Arrays.asList(selectedStudents);
                newAssignment = new Assignment(null, null, sStudent, currTemplate, null, Assignment.Type.STUDENT, selectedSubject);
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Assigned task output", "System could not determine nature"
                        + " of task."));
                return "assignTaskKantor";
            }
            assignments.add(newAssignment);
        }
        finalAssignments = assignments;
        return "assignTaskConfirm";

    }

    /**
     * This method ask business layer for assign created assignments. If assign
     * assignment is successful then {@linkplain KantroTaskController#resetClass()
     * }
     * is called and return value from {@linkplain KantroTaskController#resetClass()
     * }
     * is returned otherwise string assigntaskconfirm is returned
     *
     * @return If assign assignment is successful then {@linkplain KantroTaskController#resetClass()
     * }
     * is called and return value from {@linkplain KantroTaskController#resetClass()
     * }
     * is returned otherwise string assigntaskconfirm is returned
     * @see IAssignmentBusiness#createAssignments(java.util.List, boolean)
     */
    public String confirmAssignment() {
        try {
            assignmentB.createAssignments(finalAssignments, notifyUsers);
            printSuccMessage("Assignment:", " The assignment was successfully assignment.");
            return templateAssign();
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
            return "assigntaskconfirm";
        } catch (TaskProException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
            return "assigntaskconfirm";
        }

    }

    /**
     * This method set up state filter when rate task is called. The filter set
     * up on state to Accepted,Submitted and rejected. No students no teams.
     *
     * @return string rateTaskSum
     */
    public String loadStudentsToRate() {
        isDeadlineExpired = false;
        statesOfTask = new ArrayList<AssignmentSubmit.State>();
        statesOfTask.add(State.ACCEPTED);
        statesOfTask.add(State.SUBMITTED);
        statesOfTask.add(State.REJECTED);
        selectedStates = statesOfTask.toArray(new AssignmentSubmit.State[statesOfTask.size()]);
        return "rateTaskSum";
    }
    /**
     * This method ask business layer for all submitted assignments. Students,
     * groups and states must be choosen. If selected subject are null then
     * no task are selected. 
     * @see IAssignmentBusiness#getAssignmentsToRateByContext(java.util.List, java.util.List, java.util.List) 
     */
    public void showTaskByStudents() {
        try {
            if (selectedSubjects != null) {
                submitTasks = assignmentB.getAssignmentsToRateByContext(Arrays.asList(selectedStudents), Arrays.asList(selectedSubjects), Arrays.asList(selectedStates));
            } else {
                printErrMessage(1001, "No student was selected.");
                return;
            }
            if (!submitTasks.isEmpty()) {
                displaySubTaskForm = true;
            } else {
                printSuccMessage("Load task: ", "There were not founded task to this students.");
            }
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }
    /**
     * This method ask business layer for find all version file which were submitted
     * with submitted assignments.
     * @see IVersionBusiness#getAllVersionFileByAssingment(cz.cvut.fel.taskpro.data.entity.AssignmentSubmit) 
     */
    public void loadVersions() {
        versions = versionB.getAllVersionFileByAssingment(submitTaskChoosen);
    }
    /**
     * 
     */
    public Team teamToAssingmentSubmit() {
        if (!submitTaskChoosen.getAssignment().getType().equals(Assignment.Type.TEAM)) {
            return teamOnAssignmentSubmit;
        } else {
            return null;
        }

    }
    /**
     * This method ask business layer for update evaluated versions.
     * @see IVersionBusiness#updateVersion(java.util.List) 
     */
    public void saveEvaluationOfVersion() {
        try {
            versionB.updateVersion(versions);
            printSuccMessage("Version evaluation", "The version has been succesfuly evaluated.");
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
    }
    /**
     * This method choose all students from all kantors students. Kantors students
     * are selected based on previous filters.
     */
    public void chooseAllStundents() {
        selectedStudents = kantorStudents.toArray(new Student[kantorStudents.size()]);
    }
    /**
     * This method set selected template based on templateToSelect parameter.
     * @param templateToSelect  template to select
     */
    public void selectSingleTemplate(Template templateToSelect) {
        selectedSingleTemplate = templateToSelect;
    }

    public boolean isShowGroupsTable() {
        return showGroupsTable;
    }

    public void setShowGroupsTable(boolean showGroupsTable) {
        this.showGroupsTable = showGroupsTable;
    }

    public boolean isShowStudentsTable() {
        return showStudentsTable;
    }

    public void setShowStudentsTable(boolean showStudentsTable) {
        this.showStudentsTable = showStudentsTable;
    }

    public boolean isShowTeamsTable() {
        return showTeamsTable;
    }

    public void setShowTeamsTable(boolean showTeamsTable) {
        this.showTeamsTable = showTeamsTable;
    }

    public Subject[] getSelectedSubjects() {
        return selectedSubjects;
    }

    public void setSelectedSubjects(Subject[] selectedSubjects) {
        this.selectedSubjects = selectedSubjects;
    }

    public List<Assignment> getFinalAssignments() {
        return finalAssignments;
    }

    public void setFinalAssignments(List<Assignment> finalAssignments) {
        this.finalAssignments = finalAssignments;
    }

    public boolean isIsGroupTask() {
        return isGroupTask;
    }

    public void setIsGroupTask(boolean isGroupTask) {
        this.isGroupTask = isGroupTask;
    }

    public boolean isIsStudentTask() {
        return isStudentTask;
    }

    public void setIsStudentTask(boolean isStudentTask) {
        this.isStudentTask = isStudentTask;
    }

    public boolean isIsTeamTask() {
        return isTeamTask;
    }

    public void setIsTeamTask(boolean isTeamTask) {
        this.isTeamTask = isTeamTask;
    }

    public List<GroupTaskPro> getKantorGroups() {
        return kantorGroups;
    }

    public void setKantorGroups(List<GroupTaskPro> kantorGroups) {
        this.kantorGroups = kantorGroups;
    }

    public List<Template> getKantorTemplate() {
        return kantorTemplate;
    }

    public void setKantorTemplate(List<Template> kantorTemplate) {
        this.kantorTemplate = kantorTemplate;
    }

    public Template[] getSelectedTemplate() {
        return selectedTemplate;
    }

    public void setSelectedTemplate(Template[] selectedTemplate) {
        this.selectedTemplate = selectedTemplate;
    }

    public Team[] getSelectedTeam() {
        return selectedTeam;
    }

    public void setSelectedTeam(Team[] selectedTeam) {
        this.selectedTeam = selectedTeam;
    }

    public List<Student> getKantorStudents() {
        return kantorStudents;
    }

    public void setKantorStudents(List<Student> kantorStudents) {
        this.kantorStudents = kantorStudents;
    }

    public List<Subject> getKantorSubjects() {
        return kantorSubjects;
    }

    public void setKantorSubjects(List<Subject> kantorSubjects) {
        this.kantorSubjects = kantorSubjects;
    }

    public List<Team> getKantorTeam() {
        return kantorTeam;
    }

    public void setKantorTeam(List<Team> kantorTeam) {
        this.kantorTeam = kantorTeam;
    }

    public GroupTaskPro[] getSelectedGroup() {
        return selectedGroup;
    }

    public void setSelectedGroup(GroupTaskPro[] selectedGroup) {
        this.selectedGroup = selectedGroup;
    }

    public Student[] getSelectedStudents() {
        return selectedStudents;
    }

    public void setSelectedStudents(Student[] selectedStudents) {
        this.selectedStudents = selectedStudents;
    }

    public Subject getSelectedSubject() {
        return selectedSubject;
    }

    public void setSelectedSubject(Subject selectedSubject) {
        this.selectedSubject = selectedSubject;
    }

    public List<AssignmentSubmit> getSubmitTasks() {
        return submitTasks;
    }

    public void setSubmitTasks(List<AssignmentSubmit> submitTasks) {
        this.submitTasks = submitTasks;
    }

    public boolean isDisplaySubTaskForm() {
        return displaySubTaskForm;
    }

    public void setDisplaySubTaskForm(boolean displaySubTaskForm) {
        this.displaySubTaskForm = displaySubTaskForm;
    }

    public AssignmentSubmit getSubmitTaskChoosen() {
        return submitTaskChoosen;
    }

    public void setSubmitTaskChoosen(AssignmentSubmit submitTaskChoosen) {
        this.submitTaskChoosen = submitTaskChoosen;
    }

    public List<VersionFile> getVersions() {
        return versions;
    }

    public void setVersions(List<VersionFile> versions) {
        this.versions = versions;
    }

    public Team getTeamOnAssignmentSubmit() {

        return teamOnAssignmentSubmit;
    }

    public void setTeamOnAssignmentSubmit(Team teamOnAssignmentSubmit) {
        this.teamOnAssignmentSubmit = teamOnAssignmentSubmit;
    }

    public Template getSelectedSingleTemplate() {
        return selectedSingleTemplate;
    }

    public void setSelectedSingleTemplate(Template selectedSingleTemplate) {
        this.selectedSingleTemplate = selectedSingleTemplate;
    }

    public boolean isNotifyUsers() {
        return notifyUsers;
    }

    public void setNotifyUsers(boolean notifyUsers) {
        this.notifyUsers = notifyUsers;
    }

    public AssignmentSubmit.State[] getSelectedStates() {
        return selectedStates;
    }

    public void setSelectedStates(AssignmentSubmit.State[] selectedStates) {
        this.selectedStates = selectedStates;
    }

    public List<AssignmentSubmit.State> getStatesOfTask() {
        return statesOfTask;
    }

    public void setStatesOfTask(List<AssignmentSubmit.State> statesOfTask) {
        this.statesOfTask = statesOfTask;
    }
}
